package main.synch;

import main.Link.LinkArray;
import main.Link.PVCode;
import main.Link.SQLLink;
import main.SQL.MsSQLConnect;
import main.SQL.SQLRsrc;
import main.SQL.SQLTaskRsrc;
import main.Trees.ProjectNode;
import main.reports.BusyDialog;

import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/**
 * Created by a_lyulyasov on 09.06.14.
 */
public class UpdateProjectRaThread extends Thread {

    private ProjectNode curProject;
    private LinkArray linkTableArray;
    private Connection connSQL;
    private HashMap<String, SQLRsrc> rsrcs;
    private ArrayList<ProjectNode> updateTask;
    private int tasks, curCount;
    private BusyDialog busyDlg;

    //region UpdateProjectRaThread(ProjectNode curProject, LinkArray linkTableArray, HashMap<String, SQLRsrc> rsrcs) - конструктор класса
    public UpdateProjectRaThread(ProjectNode curProject, LinkArray linkTableArray, HashMap<String, SQLRsrc> rsrcs) {
        this.curProject = curProject;
        this.linkTableArray = linkTableArray;
        this.rsrcs = rsrcs;
    }
    //endregion

    //region run() - запуск потока перерасчета
    public void run() {
        try {
            busyDlg = new BusyDialog("Пересчет назначений ресурсов", "<html>Подождите, пожалуйста.<br> Идет пересчет назначений ресурсов</html>");
            busyDlg.start();

            connSQL = MsSQLConnect.ConnectDB("Factage");

            tasks = 0;
            countTasks(curProject);

            curCount = 0;
            updateTask = new ArrayList<>();
            checkRaRecursion(curProject);

            updateTasks();

            connSQL.close();

            busyDlg.setDescription("<html>Пересчет назначений завершен.<br> <br>Для завершения нажмите \"Готово\"</html>");
            busyDlg.stopBusy();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //endregion

    //region checkRaRecursion(ProjectNode node) - рекурсия работ для пересчета, вызов из run()
    private void checkRaRecursion(ProjectNode node) {
        if (node.isTask()) {
            curCount++;
            busyDlg.setDescription("<html>Подождите, пожалуйста, пересчитываю назначения.<br>Обрабатываю работу: "+curCount+" из "+tasks+"...</html>");
            sumLinks(node);
        } else {
            if (node.getChildCount() > 0) {
                for (ProjectNode child : node.getChildren()) {
                    checkRaRecursion(child);
                }
            }
        }
    }
    //endregion

    //region countTasks(ProjectNode node) - счетчик работ рекурсия, вызов из run()
    private void countTasks(ProjectNode node) {
        if (node.isTask()) {
            tasks++;
        } else {
            if (node.getChildCount() > 0) {
                for (ProjectNode child : node.getChildren()) {
                    countTasks(child);
                }
            }
        }
    }
    //endregion

    //region sumLinks(ProjectNode task) - пересчет назначений по работе, вызов из checkRaRecursion()
    private void sumLinks(ProjectNode task) {
        BigDecimal trPv, trMech, trMr, trT;
        trPv = new BigDecimal(0);
        trMech = new BigDecimal(0);
        trMr = new BigDecimal(0);
        trT = new BigDecimal(0);

        for (SQLLink link : linkTableArray.getLinkArray()) {
            if (link.getTaskId() != task.getId()) continue;

            if (link.getPv()) trPv = trPv.add(link.getPvVol());
            trMech = trMech.add(link.getMechVol());
            trMr = trMr.add(link.getMrVol());
            trT = trT.add(link.getTVol());
        }


        task.getRsrc().clear();
        if (trPv.compareTo(new BigDecimal(0.001)) == 1) {
            SQLRsrc rsr = rsrcs.get(task.getTaskCodeValue());
            if (rsr != null) {
                SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trPv.doubleValue(), "", curProject.getDbName(), curProject.getId());
                task.getRsrc().add(tr);
                task.setTaskUse("true");
            }
        }

        if (trMech.compareTo(new BigDecimal(0.001)) == 1) {
            SQLRsrc rsr = rsrcs.get("MECH");
            if (rsr != null) {
                SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trMech.doubleValue(), "", curProject.getDbName(), curProject.getId());
                task.getRsrc().add(tr);
                task.setTaskUse("true");
            }

        }
        if (trT.compareTo(new BigDecimal(0.001)) == 1) {

            //region Description
            PVCode code = new PVCode();
            String rsrcShortName = code.getRsrcShortName(task.getTaskCodeValue());

            if (!rsrcShortName.equals("T") && task.getConstrCode() != null) {
                rsrcShortName = rsrcShortName + "-" + task.getConstrCode();
            } else if (!rsrcShortName.equals("T") && curProject.getProjCode() != null) {
                rsrcShortName = rsrcShortName + "-" + curProject.getProjCode();
            }
            //endregion

            SQLRsrc rsr = rsrcs.get(rsrcShortName);
            if (rsr == null) {
                //JOptionPane.showMessageDialog(this, "Ресурс с ID:\"" + rsrcShortName + "\" не был найден.\n Будет назначен общий ресурс трудозатрат.\n\n", "Предупреждение", JOptionPane.ERROR_MESSAGE);
                rsr = rsrcs.get("T");
            }

            SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trT.doubleValue(), "", curProject.getDbName(), curProject.getId());
            task.getRsrc().add(tr);
            task.setTaskUse("true");

        }
        if (trMr.compareTo(new BigDecimal(0.001)) == 1) {
            SQLRsrc rsr = rsrcs.get("MR");
            if (rsr != null) {
                SQLTaskRsrc tr = new SQLTaskRsrc(0, task.getId(), rsr.getRsrcId(), 0, rsr.getRsrcName(), rsr.getRsrcType(), rsr.getRsrcShortName(), trMr.doubleValue(), "", curProject.getDbName(), curProject.getId());
                task.getRsrc().add(tr);
                task.setTaskUse("true");
            }
        }
        updateTask.add(task);
    }
    //endregion

    //region updateTasks() - Обновление назначений ресурсов в SQL, вызывается из addLinks()
    private void updateTasks () {
        busyDlg.setDescription("<html>Подождите, пожалуйста, удаляю старые назначения...</html>");
        HashSet<Integer> taskSet = new HashSet<>();
        ArrayList<Integer> rsrcList = new ArrayList<>();

        for (ProjectNode task : updateTask) {
            taskSet.add(task.getId());
        }

        try {
            CallableStatement stmt;
            ResultSet rs;

            stmt = connSQL.prepareCall("{call getTaskRsrc(?, ?)}");
            stmt.setString(1, curProject.getDbName());
            stmt.setInt(2, curProject.getId());

            rs = stmt.executeQuery();

            busyDlg.setDescription("<html>Подождите, пожалуйста, удаляю старые назначения.</html>");
            while (rs.next()) {
                if (taskSet.contains(rs.getInt("task_id"))) {
                    rsrcList.add(rs.getInt("id"));
                }
            }
            System.out.println("rsr: " + rsrcList.size());

            stmt = connSQL.prepareCall("{call deleteTaskRsrc(?)}");
            for (int id : rsrcList) {
                stmt.setInt(1, id);
                stmt.addBatch();
            }

            stmt.executeBatch();

//            stmt = connSQL.prepareCall("{call prepareBatchTaskRsrc(?, ?, ?)}");
//
//            int a = 0;
//            for (ProjectNode task : updateTask) {
//                a++;
//                busyDlg.setDescription("<html>Подождите, пожалуйста, удаляю старые назначения.<br> Обрабатываю работу: "+a+" из "+updateTask.size()+"... </html>");
//                stmt.setString(1, curProject.getDbName());
//                stmt.setInt(2, curProject.getId());
//                stmt.setInt(3, task.getId());
//                stmt.addBatch();
//            }
//            busyDlg.setDescription("<html>Подождите, пожалуйста, удаляю старые назначения.<br> Отправляю запрос на удаление...</html>");
//
//            start = System.currentTimeMillis();
//            stmt.executeBatch();
//            finish = (System.currentTimeMillis() - start) / 1000;
//            System.out.println("prepareBatchTaskRsrc: " + finish);
//
//            stmt.close();

            busyDlg.setDescription("<html>Подождите, пожалуйста, сохраняю новые назначения...</html>");
            stmt = connSQL.prepareCall("{call insertTaskRsrcBatch(?, ?, ?, ?, ?)}");

            for (ProjectNode task : updateTask) {
                for (SQLTaskRsrc tr : task.getRsrc()) {
                    stmt.setString(1, tr.getDbName());
                    stmt.setInt(2, curProject.getId());
                    stmt.setInt(3, task.getId());
                    stmt.setInt(4, tr.getRsrcId());
                    stmt.setFloat(5, (float) tr.getPlannedUnits());
                    stmt.addBatch();
                }
            }
            busyDlg.setDescription("<html>Подождите, пожалуйста, сохраняю новые назначения.<br> Отправляю запрос на сохранение...</html>");
            stmt.executeBatch();

            stmt.close();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    //endregion

}



